package com.sihai.ehr.service.impl;

import com.sihai.core.*;
import com.sihai.ehr.jdbc.Department;
import com.sihai.ehr.jdbc.DepartmentService;
import com.sihai.ehr.model.biz.AuditType;
import com.sihai.ehr.model.biz.Auditing;
import com.sihai.ehr.model.sys.AuditStatus;
import com.sihai.ehr.model.sys.Organization;
import com.sihai.ehr.model.sys.OrganizationAuditing;
import com.sihai.ehr.repository.AuditingRepository;
import com.sihai.ehr.service.OrganizationService;
import org.apache.commons.lang.StringUtils;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Result;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * @author wxn
 * @since 12-5-24 上午1:14
 */

@Service("organizationService")
public class OrganizationServiceImpl implements OrganizationService {
    @Resource
    private DataAccessor dataAccessor;

    @Resource
    private AuditingRepository auditingRepository;

    @Override
    public Organization get(Long id) {
        if (id == null) {
            return null;
        }
        return dataAccessor.get(Organization.class, id);
    }

    @Override
    public LimitedList<Organization> search(final Organization organization, Limit limit, Sorter sorter) {
        if (organization == null || organization.getStatus() == null) {
            return dataAccessor.findByClass(Organization.class, limit, sorter);
        }

        return dataAccessor.findByQuery(Organization.class, new QueryCreator() {
            @Override
            public Query createQuery(Session session) {
                DynamicQuery dynamicQuery = new DynamicQuery("from Organization o where o.cancel <> 1 ");
                dynamicQuery.appendIfNotNull("and o.status = :status", "status", organization.getStatus());
                if (organization.getParent() != null) {
                    dynamicQuery.appendIfNotNull("and o.parent.id = :parentId", "parentId", organization.getParent().getId());
                }
                dynamicQuery.appendIfNotNull("and o.fullName like :fullName", "fullName", organization.getFullName());

                return dynamicQuery.build(session);
            }
        }, limit, sorter);
    }

    @Override
    public void save(Organization organization) {
        if (organization == null) {
            return;
        }
        boolean isCreate = (organization.getId() == null || organization.getId() == 0);
        boolean isChangeParent = false;

        //判断是否修改了结点位置
        if(!isCreate && organization.getParent() != null){
            Organization o = get(organization.getParent().getId());
            if(o != null && o.getId() != null && o.getId().longValue() == organization.getParent().getId().longValue()){
                isChangeParent = true;
            }
        }

        dataAccessor.save(organization);

        saveDepartment(organization, isCreate, isChangeParent); //同步到考勤表中

        //add.wxn#start.2012.12.18(保存treePath)
        if(isCreate){
            if(organization.getParent() == null){
                organization.setTreePath(String.format(",%s,", organization.getId().longValue()));
            }else{
                Organization parent = get(organization.getParent().getId());
                organization.setTreePath(String.format("%s%s,", parent.getTreePath(), organization.getId().longValue()));
            }
            dataAccessor.save(organization);

            //给第一个审核结点发消息
            auditingRepository.saveAuditingProcess(organization, 1);
        }else{
            String oldTreePath = organization.getTreePath();
            String parentPath = "";
            if(organization.getParent() != null){
                Organization parent = get(organization.getParent().getId());
                parentPath = parent.getTreePath();
            }
            String newTreePath = String.format("%s%s,", parentPath, organization.getId().longValue());
            //路径不一致时
            if(!StringUtils.equals(oldTreePath, newTreePath)){
                List<Organization> children = dataAccessor.findByHql(Organization.class, "from Organization o where o.treePath like '"+oldTreePath+"%'", null, null, null);
                if(children != null && !children.isEmpty()){
                    for(Organization o : children){
                        o.setTreePath(o.getTreePath().replaceFirst(oldTreePath, newTreePath));
                        dataAccessor.save(o);
                    }
                }
            }
        }
        //add.wxn#end.2012.12.18

        //如果是创建一个组织机构, 同时插入几条审核记录(即一个审核流程, 根据审核配置表来)
        if (isCreate && organization.getTopOrganization() != null) {//分公司不审核
            saveOrganizationAuditings(organization, 1);
        }
    }

    @Override
    public List<Organization> findChildren(Long parentId, boolean isAllField, Limit limit, Sorter sorter) {
        String temp = isAllField ? "" : "select new Organization(o.id, o.fullName) ";
        if (parentId == null) {
            return dataAccessor.findByHql(Organization.class,
                    temp + "from Organization o where o.parent is null",
                    null,
                    limit,
                    sorter);
        }

        return dataAccessor.findByHql(Organization.class,
                temp + "from Organization o where o.parent is not null and o.parent.id=?",
                new Object[]{parentId},
                limit,
                sorter);
    }

    @Override
    public List<Organization> findChildrenByTop(Long topId, Limit limit, Sorter sorter) {
        if (topId == null) {
            return null;
        }

        return dataAccessor.findByHql(Organization.class,
                "from Organization o where o.topOrganization is not null and o.topOrganization.id=? order by o.topOrganization.id",
                new Object[]{topId},
                limit,
                sorter);
    }

    @Override
    public List<Organization> findAllChildren(boolean isAllField, Limit limit, Sorter sorter) {
        String temp = isAllField ? "" : "select new Organization(o.id, o.fullName) ";
        try {
            return dataAccessor.findByHql(Organization.class,
                    temp + "from Organization o", null,
                    limit,
                    sorter);
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }

    @Override
    public LimitedList<Organization> findForAudit(Long currentId, Limit limit, Sorter sorter) {
        if (currentId == null) {
            return null;
        }

        return dataAccessor.findByHql(Organization.class,
                "from Organization o where o.cancel <> 1 and o.topOrganization.id = ? and (o.status = ? or o.status = ?)",
                new Object[]{currentId, AuditStatus.wait_audit, AuditStatus.within_audit},
                limit,
                sorter);
    }


    //查询组织机构审核流程记录

    public List<List<OrganizationAuditing>> findOrganizationAuditing(Long organizationId) {
        return auditingRepository.findByHql(OrganizationAuditing.class, "from OrganizationAuditing oa where oa.organization.id = ?", new Object[]{organizationId});
    }


    @Override
    public void saveOrganizationAuditingProcess(Long organizationId) {
        saveOrganizationAuditings(dataAccessor.get(Organization.class, organizationId), 1);
    }

    //创建审核流程

    private void saveOrganizationAuditings(Organization organization, int auditNo) {
        auditingRepository.saveAuditingProcess(organization, auditNo);
    }

    @Override
    public List<Organization> findAllChildren(Limit limit, Sorter sorter) {
        return dataAccessor.findByHql(Organization.class,
                "from Organization o where o.parent is null",
                null,
                limit,
                sorter);
    }

    @Override
    public void remove(Long organizationId) throws Exception {
        dataAccessor.delete(dataAccessor.get(Organization.class, organizationId));
        int row = departmentService.delete((int)(long)organizationId);
        if(row > 0){
            mDepartments = null;
            buildDepartmentTree();
            departmentService.batchUpdate(mDepartments);
        }
    }


    //组织架构数据写到考勤数据库中去start=============================================================================
    private DepartmentService departmentService ;
    private List<Organization> mOrganizations;
    private List<Department> mDepartments;

    //构建部门树-start
    private void buildDepartmentTree(){
        mOrganizations = findAllChildren(true, null, null);
        if(mOrganizations != null && !mOrganizations.isEmpty()){
            mDepartments = new ArrayList<Department>(mOrganizations.size());
            int index = 0;
            for(Organization org : mOrganizations){
                if(org.getParent() == null){ //查找顶层分公司
                    Department department = buildDepartment(org, null, "001", index); //001为根的编号
                    mDepartments.add(department);
                    index++;
                    findChild(org, department.getDep_no());
                }
            }
        }
    }

    private void findChild(Organization parent, String parentNo){
        if(mOrganizations != null && mOrganizations.size() > 0){
            int index = 0;
            for(Organization o : mOrganizations){
                if(o.getParent() != null && o.getParent().getId().longValue() == parent.getId().longValue()){
                    Department department = buildDepartment(o, parent, parentNo, index);
                    mDepartments.add(department);
                    findChild(o, department.getDep_no());
                    index++;
                }
            }
        }
    }

    private Department buildDepartment(Organization o, Organization parent, String parentNo, int index){
        Department department = new Department();
        department.setDep_serial((int)(long)o.getId()); //考勤数据库部门id与ehr组织架构id同
        department.setDep_name(o.getFullName());
        department.setDep_parent(parent == null ? 10000 : (int)(long)parent.getId());
        department.setDep_order(index);
        department.setDep_no(parentNo+"0"+index);
        department.setDep_rule("0");
        return department;
    }
    //构建部门树-end

    //初始化部门数据库
    public boolean initDepartmentDB()throws Exception{
        buildDepartmentTree();
        if(mDepartments != null && !mDepartments.isEmpty()){
            for(Department department : mDepartments){
                System.out.println("wxn---department: name="+department.getDep_name()+", serial="+department.getDep_serial()+", No.="+department.getDep_no()+", rule="+department.getDep_rule()+", parent="+department.getDep_parent());
            }

            if(departmentService == null){
                departmentService = new DepartmentService();
                departmentService.connection();
            }
            departmentService.initDB(mDepartments);
            //departmentService.close();

            return true;
        }

        return false;
    }

    //添加或修改部门
    private void saveDepartment(Organization organization, boolean isCreate, boolean isChangeParent){
        if(organization == null || organization.getId() == null){
            return;
        }

        try {
            Department department = new Department();
            department.setDep_serial((int)(long)organization.getId());
            department.setDep_name(organization.getFullName());
            if(organization.getParent() == null || organization.getParent().getId() == null){
                department.setDep_parent(10000);
            }else{
                department.setDep_parent((int)(long)organization.getParent().getId());
            }
            department.setDep_rule("0");

            if(departmentService == null){
                departmentService = new DepartmentService();
                departmentService.connection();
            }

            if(isCreate){
                departmentService.insert(department);
            }else{
                int row = departmentService.update(department);
                if(row > 0 && isChangeParent){
                    mDepartments = null;
                    buildDepartmentTree();
                    departmentService.batchUpdate(mDepartments);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //组织架构数据写到考勤数据库中去end=============================================================================
}
